/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.core.image.service.impl.ImageServiceImpl
   Module Description   :

   Date Created      : 2009/12/8
   Original Author   : jeff.ma
   Team              : yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.core.image.service.impl;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Random;

import javax.imageio.ImageIO;

import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.core.common.utils.ImageUtils;
import com.yaodian100.core.image.entity.TextImage;
import com.yaodian100.core.image.service.ImageService;

/**
 * @author jeff.ma
 * 
 */
public class ImageServiceImpl extends DomainServiceImpl<TextImage> implements ImageService {

	private File backgroundImage = null;
	private char[] charSet = "23456789abcdefghijkmnpqrstuvwxyz".toCharArray();
	private int textLength = 10;
	private Font font = new Font(null, Font.PLAIN, 20);
	private boolean deepColor = false;
	public static final int IMAGE_TYPE = BufferedImage.TYPE_INT_RGB;
	private int randLine = 5;
	private int width = 300;
	private int height = 100;

	/**
	 * @param randLine the randLine to set
	 */
	public void setRandLine(int randLine) {
		this.randLine = randLine;
	}

	/**
	 * @param width the width to set
	 */
	public void setWidth(int width) {
		this.width = width;
	}

	/**
	 * @param height the height to set
	 */
	public void setHeight(int height) {
		this.height = height;
	}

	/**
	 * @param backgroundImage the backgroundImage to set
	 */
	public void setBackgroundImage(String backgroundImage) {
		File bgFile = new File(backgroundImage);
		if (bgFile.exists() && bgFile.isFile()) {
			this.backgroundImage = bgFile;
		}
	}

	/**
	 * @param deepColor the deepColor to set
	 */
	public void setDeepColor(boolean deepColor) {
		this.deepColor = deepColor;
	}

	/**
	 * @param font the font to set
	 */
	public void setFont(String name, int fontSize) {
		this.font = new Font(name, Font.PLAIN, fontSize);
	}

	/**
	 * @param charSet the charSet to set
	 */
	public void setCharSet(String charSet) {
		if (charSet != null) {
			this.charSet = charSet.toCharArray();
		}
	}

	/**
	 * @param textLength the textLength to set
	 */
	public void setTextLength(int textLength) {
		this.textLength = textLength;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.core.common.service.impl.DomainServiceImpl#save(java.lang.Object)
	 */
	@Override
	@Transactional(readOnly = false)
	public TextImage save(TextImage entity) throws CoreException {
		try {
			BufferedImage image;
			if (backgroundImage != null) {
				image = ImageIO.read(backgroundImage);
				if (image.getWidth() != entity.getWight() || image.getHeight() != entity.getHigh()) {
					image = ImageUtils.resize(image, entity.getWight(), entity.getHigh());
				}
			} else {
				image = new BufferedImage(entity.getWight(), entity.getHigh(), IMAGE_TYPE);

			}
			if (entity.getText() == null) {
				entity.setText(generateText());
			}
			generateImage(image, entity);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (getDao() == null) {
			return entity;
		} else {
			return super.save(entity);
		}
	}

	private String generateText() {
		StringBuffer sb = new StringBuffer(textLength);
		Random rand = new Random(Calendar.getInstance().getTimeInMillis());
		for (int i = 0; i < textLength; i++) {
			int j = rand.nextInt(charSet.length);
			sb.append(charSet[j < 0 ? -j : j]);
		}
		return sb.toString();
	}

	private void generateImage(BufferedImage image, TextImage entity) {
		try {
			Graphics graph = image.getGraphics();// createGraphics();
			if (backgroundImage == null) {
				if (deepColor) {
					graph.setColor(Color.white);
				} else {
					graph.setColor(Color.darkGray);
				}
				graph.fillRect(0, 0, entity.getWight(), entity.getHigh());
			}
			Random rand = new Random(Calendar.getInstance().getTimeInMillis());
			char[] t = entity.getText().toCharArray();
			int x = 5 + ((entity.getWight() - 20) / (t.length * 2));
			int y = entity.getHigh() / 2;
			graph.setFont(font);
			for (int i = 0; i < t.length; i++) {
				graph.setColor(getColor(rand, deepColor));
				graph.drawString(String.valueOf(t[i]), x + rand.nextInt(5), y + rand.nextInt(20));
				// logger.debug("char:{},x:{},y:{}", new Object[] { t[i], x, y });
				x += ((entity.getWight() - 20) / t.length);
			}

			x = 5 + ((entity.getWight() - 20) / (t.length * 2));
			for (int i = 0; i < randLine; i++) {
				graph.setColor(getColor(rand, !deepColor));
				int len = ((entity.getWight() - 20) / randLine) + rand.nextInt(20);
				graph.drawLine(x, y + rand.nextInt(50), x + len, y + rand.nextInt(50));
				x += ((entity.getWight() - 20) / randLine);
			}
			graph.dispose();

			ByteArrayOutputStream bouts = new ByteArrayOutputStream();
			ImageIO.write(image, entity.getType(), bouts);
			bouts.flush();
			entity.setBody(bouts.toByteArray());
			bouts.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private Color getColor(Random rand, boolean deep) {
		// for rgb
		int[] c = { 127, 127, 127 };
		for (int i = 0; i < 3; i++) {
			int j = Math.abs(rand.nextInt(127));
			if (deep) {
				c[i] -= j;
			} else {
				c[i] += j;
			}
		}
		Color color = new Color(c[0], c[1], c[2]);

		// for hsb(色彩HUE飽和度Saturation和亮度Brightness)
		// float[] c = { 0.0f, 0.5f, 0.5f };
		// c[0] = Math.abs(rand.nextInt(360));
		// if (deep) {
		// c[1] += Math.abs(rand.nextFloat() / 2);
		// c[2] -= Math.abs(rand.nextFloat() / 3);
		// } else {
		// c[1] -= Math.abs(rand.nextFloat() / 2);
		// c[2] += Math.abs(rand.nextFloat() / 2);
		// }
		// Color color = Color.getHSBColor(c[0], c[1], c[2]);
		// logger.debug("color:{}/{}", color, c);
		return color;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.core.image.service.ImageService#create(int, int)
	 */
	@Override
	public TextImage create(int width, int height) {
		TextImage img = null;
		if (width == 0 || height == 0) {
			img = new TextImage(this.width, this.height);
		} else {
			img = new TextImage(width, height);
		}
		return save(img);
	}
}
